#ifndef movegen_h
#define movegen_h

#include <move.h>
#include <bitboard.h>


#define MAX_N_MOVES 256  // it really should be safe


// forward declaration
struct position_t;


/*
 * Initialize the move generation data.
 *
 * Call this function before every other function of this module.
 */
void movegen_init();


/*
 * Pawns left catures.
 *
 * Return the subset of opp of squares attacked from the left by pawns
 * (in bb) of color stm.
 */
bitboard_t movegen_pawns_left_captures(bitboard_t bb,
				       int stm,
				       bitboard_t opp);


/*
 * Pawns right catures.
 *
 * Return the subset of opp of squares attacked from the right by
 * pawns (in bb) of color stm.
 */
bitboard_t movegen_pawns_right_captures(bitboard_t bb,
					int stm,
					bitboard_t opp);

/* !!! */
bitboard_t movegen_knight_attacks(int from);

/* !!! */
bitboard_t movegen_bishop_attacks(int from, bitboard_t occ);

/* !!! */
bitboard_t movegen_rook_attacks(int from, bitboard_t occ);

/* !!! */
bitboard_t movegen_king_attacks(int from);




/*
 * Generate all the legal moves for the position pos.
 *
 * Moves are stored in the array buf, and their number is returned.
 * The user is responsible for passing a pointer to an array which is
 * big enough. A safe length for the array is given by MAX_N_MOVES.
 */
int movegen_legal_moves(const struct position_t* pos, move_t* buf);


/*
 * Generate pseudo-legal moves for position pos.
 *
 * Moves are stored in the array buf, and their number is returned.
 * The user is responsible for passing a pointer to an array which is
 * big enough. A safe length for the array is given by
 * MAX_N_MOVES. This function assumes that the side to move is not
 * under check.
 */
int movegen_moves_nocheck(const struct position_t* pos, move_t* buf);


/*
 * Generate the possible captures in pos.
 *
 * The same as movegen_nocheck_moves, but returns only the captures.
 * This function assumes that the side to move is not under check.
 */
int movegen_captures(const struct position_t* pos, move_t* buf);


/*
 * Generate promotions to queen.
 *
 * The same as movegen_nocheck_moves, but returns only promotions to
 * queen.  This function assumes that the side to move is not under
 * check.
 */
int movegen_queen_promotions(const struct position_t* pos, move_t* buf);

/*
 * Generate pseudo-legal moves for position pos.
 *
 * Moves are stored in the array buf, and their number is returned.
 * The user is responsible for passing a pointer to an array which is
 * big enough. A safe length for the array is given by MAX_N_MOVES.
 * This function assumes that the side to move is under check.
 */
int movegen_check_evasion(const struct position_t* pos,
			  move_t* buf);
/*
 * Tell if the side to move is under check.
 *
 * Returns the bitboard of opponent pieces attacking the king.
 */
bitboard_t movegen_detect_check(const struct position_t* pos);


/* 
 * Verify that m is a legal move for pos.
 *
 * If the move is illegal the null move is returned.  Otherwise, the
 * returned move is m itself, possibly decorated with extra
 * information. The null move is also returned in case of error
 * due to memory allocation.
 */
move_t movegen_test_legality(const struct position_t* pos,
			     move_t m);

/*
 * Verify if m is a legal move.
 *
 * The move m must have been obtained by a call to one of the
 * functions generating pseudo-legal moves (called on the same
 * position).
 */
int movegen_verify_move(const struct position_t* pos, move_t m);

/*
 * Verify if m is pseudo-legal for pos.
 *
 * Moves generated by movegen_moves_nocheck, movegen_captures,
 * movegen_queen_promotions, movegen_check_evasion will return 1.  A
 * move is pseudo-legal if satisfy chess rules except that it may
 * leave the king under check. Are also pseudo-legal castlings where
 * the king passes through attacked squares.
 */
int movegen_is_pseudo_legal(const struct position_t* pos,
			    move_t m);

/*
 * Verify if m put the opponent king under check.
 *
 * Return 1 if m is checking, 0 otherwise. m must be a pseudo-legal
 * move for pos.
 */
int movegen_is_checking(const struct position_t* pos, move_t m);


/*
 * Static exchange evaluation.
 *
 * Return a score in centipawns corresponding to the value of the move
 * m, by considering all possible following capture sequences in the
 * destination square of m.
 */
int movegen_see(const struct position_t* pos, move_t m);


#endif  // movegen_h
